import torch
import torch.nn as nn


torch.where(condition,other)  # 必须两个？
torch.nonzero(condition)  # 返回一个值 一个值的坐标
#沿着该dim维度选择填充值；返回值shape和index的shape一样；设dim维度数据大小为N,那么index取值范围为0~N-1
torch.gather(tensor,dim,index)  # 沿着该dim维度,index和tensor在前dim轴之前和之后的shape一样(index在dim该维度,shape值需要大于等于1)，
  # 代表该位置的值沿指定dim维度的index选择填充值(index范围为tensor的dim维数据列大小)输出同index shape 一个值一个值取
level_rois.repeat(4,1)  # 重复4行一列,里面的长度不能小于tensor维度长度
torch.masked_select(a, mask)
torch.index_select(a,0,torch.tensor([0, 2]))
torch.index_fill(dim,index,val) #dim维度上，按参数index中的索引数确定的顺序，将原tensor用参数val填充
torch.take(a, torch.LongTensor([0, 1, 5]))  # 在原来Tensor的shape基础上打平，然后在打平后的Tensor上进行索引
torch.topk() # 取top k
torch.view() # 方法约定了不修改数组本身，只是使用新的形状查看数据;共享底层内存数据
torch.bitwise_not() # 按位取反
images.select(dim=0,index=1)按index中选定的维度对tensor进行切片  # tensor 切片语法;image:[32,56,57];等价于images[0,:,:],返回shape[56,57]
torch.max() #整合进了 np.max np.maximum;要是传一个tensor就是max,传两个tensor就是maximum
torch.stack([x, y, w, h], dim=1)
contiguous() # transpose、permute 操作后，要执行view等变形操作，需要使用contigugous以保证内存一维数组顺序一致
is_contiguous #  Tensor底层一维数组元素的存储顺序与Tensor按行优先一维展开的元素顺序是否一致(https://zhuanlan.zhihu.com/p/64551412)
torch.einsum('') # 爱因斯坦求和表达式()
tensor.type(torch.IntTensor) #tensor 改变数据类型
torch.narrow(input, dim, start, length)#dim：沿着的维度,start:开始索引，length:保留几个值
F.pad(x, (1, 1, 1, 1)) # 每两个为一组,从最后一个维度开始
torch.split(): x,y,w,h = torch.split(arr,1,1) // arr:[4,4]
    当split_size_or_sections为int时，tenor结构和split_size_or_sections，正好匹配，那么ouput就是大小相同的块结构。如果按照split_size_or_sections结构，tensor不够了，那么就把剩下的那部分做一个块处理。
    当split_size_or_sections 为list时，那么tensor结构会一共切分成len(list)这么多的小块，每个小块中的大小按照list中的大小决定，其中list中的数字总和应等于该维度的大小，否则会报错（注意这里与split_size_or_sections为int时的情况不同）
torch.chunk():# 很像torch.split，区别：
    chunks只能是int型，而split_size_or_section可以是list。
    chunks在时，不满足该维度下的整除关系，会将块按照维度切分成1的结构。而split会报错。
torch.split_with_sizes()  # 这个跟tf的split才有点像 
      也很像torch.split,
      只支持传入list,list里之和等于维度数,长度等于切几个
###############################################

# nn.Module:
    # 将A注册成寄存器变量:A是tensor;寄存器变量访问快
        # self.register_buffer('A', A)
# REW:modules()返回的iterator不止包含子模块，而children()只包含子模块，这是区别

## REW:返回符合某一条件的index
condition=torch.eq(ant,0)
ix = torch.nonzero(condition) # ix[[x,y],[x,y]...]
ant[list(zip(*ix))] # list(zip(*ix)):[[x,x,..],[y,y,..]]

x,y,w,h = torch.split_with_sizes(rois,(1,1,1,1),dim=2)

#pos1:[N,3,10];keepdim:[N,1,10];没有keepdim：就返回[N,10]
pos1.long().sum(1, keepdim=True)
# 3D卷积

# 双sort 技巧 #
num=2
loss_c = loss_c.view(num, -1)  # [N,n_pri]
_, loss_idx = loss_c.sort(1, descending=True)
_, idx_rank = loss_idx.sort(1)